package taller2.model.graph.algorithms;

import taller2.interfaces.Connection;
import taller2.interfaces.Graph;
import taller2.interfaces.Node;
import taller2.utils.Constants;
import taller2.utils.Constants.Colores;

public class CyclesDetectionApplicator extends AlgorithmApplicatorImpl{
	private int cont;
	private static final String path = Constants.savedGraphsPath + "CerraduraTransitiva";		
	private boolean directed;
	
	public CyclesDetectionApplicator(){
		super();
		cont = 0;
		directed = true;
	}
	
	// applies the algorithm to the graph
	// and stores the path's and pseudocode lines
	public void solveProblem(Graph g){
		
		if(noGraph(g) || !noGraphPaths() || !noPseudocodeLines())
			return;
		
		g.killFluxes();
		g.killWeights();
		g.unselectConnections();		
		g.unselectNodes();		
		directed = g.isDirected();
		
		g.save(path);
			
		boolean encontrado = false;

		cont = 0;
		saveGraph(g,path+cont);            			
        pseudocodeLines.add(0);
		cont++;
						
		for(Node start : g.getNodes()){
			start.changeColor(Colores.green);	
			
			saveGraph(g,path+cont);            			
	        pseudocodeLines.add(1);
			cont++;	
			
			start.select();
			
			encontrado = findCyclesStartingWith(start,start,g);
			if (encontrado)
				break;

			start.changeColor(Colores.red);	
			unmark(g);
		}

		graphPaths.add(path+(cont-1));            			
        pseudocodeLines.add(3);

			
		saveGraph(g,path+cont);
			
		if (encontrado)
			pseudocodeLines.add(4);
		else
			pseudocodeLines.add(5);
			
		cont++;
			
		g.load(path);
	}
	
	private boolean findCyclesStartingWith(Node start,Node act,Graph g){
		if(!act.isSelected()){
			act.mark();
		}
		
		for(Connection connection : act.getConnections()){
			Node otherNode = connection.getOtherNode();
			
			boolean areEqual = otherNode.equals(start);

			if(areEqual){
				connection.select();
				return true;				
			}

			boolean unused = !otherNode.isMarked() && !otherNode.isSelected();
			if(unused){
				start.unselect();
				start.changeColor(Colores.green);	
				otherNode.changeColor(Colores.purple);

				saveGraph(g,path+cont);            			
				pseudocodeLines.add(2);
				cont++;

				start.select();
				
				if(findCyclesStartingWith(start,otherNode,g)){
					connection.select();
					return true;							
				}
			}
		}
		return false;
	}
	
	private void unmark(Graph g){
		for(Node n: g.getNodes()){
			if(!n.isSelected()){
				n.unmark();
				n.changeColor(Colores.yellow);
			}
		}
	}
	
	public void save(String path){
	};

	public void load(String path){
	}

	public String getStartingGraphPath() {
		if(graphPaths == null || graphPaths.isEmpty())
			return "";
		return graphPaths.get(0);
	}
	
	@Override
	public int getHighlightedWordNumber() {
		return -1;
	}

	public boolean wasDirected() {
		return directed;
	}
}
